// Copyright (C) 2007 Gameloft. All rights reserved.
// GAMELOFT PROPRIETARY/CONFIDENTIAL.
//
// Author: Laevo

#pragma once
#include "Point.h"
#include "Rect.h"
#include "Texture.h"
#include "Display.h"
#include "IPLWrappingFunctions.h"

#define FADE_IN		-1
#define FADE_OUT	1
#define FADE_STEPS	0x35
extern int _savedSelectionIdx;


class Graphics
{
public:
	/// @brief flags of flags
	enum
	{
		HCENTER		= 0x00000020,
		VCENTER		= 0x00000200,
		LEFT		= 0x00000010,
		RIGHT		= 0x00000040,
		TOP			= 0,
		BOTTOM		= 0x00000400,
		BASELINE	= 0,
		SOLID		= 0,
		DOTTED		= 1,
		FLIP_X		= 0x01,
		FLIP_Y		= 0x02,
		ROTATE_90   = 0x04,
		ALPHA_BLEND = 0x08,
		LEFT_TOP    = LEFT | TOP,
		HV_CENTER   = HCENTER | VCENTER,
	};

	Graphics();
	~Graphics();

	// @brief draw graphic
	void DrawRegion(const TexInfo *tex, int dx, int dy, int sx, int sy, int sw, int sh, int flags = 0);
	void DrawRegion(int iTex, int dx, int dy, int sx, int sy, int sw, int sh, int flags = 0);

#ifdef _OptimizePaintFrame
	void Flush2D();
#endif

	void Flush3D();

#ifdef _TestEnable
	void DrawRegionIn2D(const Texture *tex, int dx, int dy, int sx, int sy, int sw, int sh, int flags = 0);	
	void DrawCircleTest(int x, int y, int radius);
#endif
	void DrawRegionIn3D(const ObjCommonRenderInfo & texInfo);

	void DrawImage(int iTex, int dx, int dy, float scaleX = 1.0f);
	void SetColor(int argb);
	void SetTexColor(int argb);
	void DrawLine(int xB, int yB, int xE, int yE, int lineWidth = 1);
	void DrawRect(int x, int y, int w, int h, int border = 1);
	void DrawBorderedRect(int x, int y, int w, int h);
	void FillRect(int x, int y, int w, int h);
	void DrawCircle(int x, int y, int radius);
	void FillTriangle(int x0, int y0, int x1, int y1, int x2, int y2);
	void DrawRay(int x, int y, int arcAngle, int length, int angle);
	void DrawPoint(int x, int y);

	bool PaintAndUpdateTransition(int kindOf, bool paint);

	static bool IsHVCenter(){ return (g2DCommRI.transform&(IS_ROT|IS_SCALE)) || mUseHVCenter;};

	//void DrawWave(int iTex, int dx, int dy, int counter);

	//clip
	/// @brief Set the current clip to the rectangle specified by the given coordinates.
	///
	/// Rendering operations have no effect outside of the clipping area.
	/// @attention Some functions like DrawLine_NoClip_NoTranslat ignore the clip.
	///	@param[in]	x	the x coordinate of the new clip rectangle.
	///	@param[in]	y	the y coordinate of the new clip rectangle.
	///	@param[in]	width	the width of the new clip rectangle.
	///	@param[in]	height	the height of the new clip rectangle.
	void SetClip(int x, int y, int width, int height);
	/// @brief Reset the current clip to the entire destination image.
	void ResetClip();
	/// @brief Get the Y offset of the current clipping area, relative to the coordinate system origin of this graphics context. 
	///	@return	Y offset of the current clipping area.
	int GetClipX();
	/// @brief Get the X offset of the current clipping area, relative to the coordinate system origin of this graphics context. 
	///	@return	X offset of the current clipping area.
	int GetClipY();
	/// @brief Get the width of the current clipping area. 
	///	@return	width of the current clipping area.
	int GetClipWidth();
	/// @brief Get the height of the current clipping area. 
	///	@return	height of the current clipping area.
	int GetClipHeight();

	inline void Translate(GLfloat x, GLfloat y, GLfloat z) {_translateX += x, _translateY += y, _translateZ += z;}
	inline void ResetTranslate() {_translateX = 0, _translateY = 0, _translateZ = 0;}

#ifdef USE_BUFFER_TEXTURE	
	void DrawSymetryPoints(int orgX, int orgY, int x, int y, bool isOdd);
	void DrawCircle2(int orgX, int orgY, int r);
	void DrawArc(int x, int y, int width, int height, int startAngle, int arcAngle);
#endif

	void SetTexMgr(TextureManager * texMgr) {_pTexMgr = texMgr;};

	//static int autoZ;

private:
	Rect2D _clipR;
	TextureManager * _pTexMgr;
	static bool mUseHVCenter;
	bool mUseClip;
	bool mUseVertexColors;

	//clip
	void _clipRect2Gfx(int *x,int *y,int *w,int *h);
	bool _clipRect2Tex(int *dx,int *dy, int *mx,int *my,int *mw,int *mh);

#ifdef USE_BUFFER_TEXTURE
	u16 _nativeColor;    
	int _colorARGB;
	int	_pixShift; //if depth is 8, no shift, if 12 or 16, shift 1 ( means * 2)
	int	_pixPitch;
	u8* _pixBuffer;
	void*	_getOffset(int x, int y);
	inline void _drawPoint(void *dst);
	//inline void _drawPoint(int x, int y);
	void _drawPoint(int x, int y);
#endif
	GLfloat _nativeColorR;
	GLfloat _nativeColorG;
	GLfloat _nativeColorB;
	GLfloat _nativeColorA;
	
	// RUIZD: Change
	// ObjCommonRenderInfo _texInfo;

	bool _bUseTexColor;
	GLfloat _texColorR;
	GLfloat _texColorG;
	GLfloat _texColorB;
	GLfloat _texColorA;
	void ResetTexColor();

	tIPLGeometry  _geom;

	GLfloat _translateX;
	GLfloat _translateY;
	GLfloat _translateZ;
};

typedef Graphics cGfx;

inline int Graphics::GetClipX() {
	return _clipR.x;// - m_translate[0];
}
inline int Graphics::GetClipY() {
	return _clipR.y;// - m_translate[1];
}
inline int Graphics::GetClipWidth() {
	return _clipR.w;// - _clipR.x - m_translate[0];
}
inline int Graphics::GetClipHeight() {
	return _clipR.h;// - _clipR.y - m_translate[1];
}
inline void cGfx::ResetClip()
{
	mUseClip = false;
	_clipR.x = _clipR.y = 0;
	_clipR.w = SCREEN_WIDTH;
	_clipR.h = SCREEN_HEIGHT;
}

#define GFX_RGB(r,g, b) (r|g<<8|b<<16|0xff000000)
#define RGBA(r,g,b,a)(b|(g<<8)|(r<<16)|(a<<24))